package cn.xllyd.service.impl;

import cn.xllyd.doc.OrderDoc;
import cn.xllyd.dto.OrderSearchDto;
import cn.xllyd.mapping.HighlightResultMapper;
import cn.xllyd.repository.OrderRepository;
import cn.xllyd.result.PageList;
import cn.xllyd.service.IOrderEsService;
import cn.xllyd.vo.AggsPageList;
import cn.xllyd.vo.AggsResult;
import org.springframework.util.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class OrderEsServiceImpl implements IOrderEsService {
    @Autowired
    private OrderRepository OrderRepository;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
    
    @Override
    public void onLineOrder(OrderDoc orderDoc) {
        OrderRepository.save(orderDoc);
    }

    @Override
    public PageList<OrderSearchDto> search(OrderSearchDto orderSearchDto) {
        // 1.创建组合条件对象
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        // 1.2.设置订单名称模糊查询
        if (!StringUtils.isEmpty(orderSearchDto.getKeyword())){
            boolQuery.must(QueryBuilders.matchQuery("name", orderSearchDto.getKeyword()));
        }
        // 1.3.设置订单分类精准查询
        if (!StringUtils.isEmpty(orderSearchDto.getCourseTypeId())){
            boolQuery.filter(QueryBuilders.termQuery("courseTypeId", orderSearchDto.getCourseTypeId()));
        }

        // 1.4.设置订单等级精准查询
        if (!StringUtils.isEmpty(orderSearchDto.getGradeName())){
            boolQuery.filter(QueryBuilders.termQuery("gradeName", orderSearchDto.getGradeName()));
        }

        // 1.3.设置订单收费方式精准查询
        if (!StringUtils.isEmpty(orderSearchDto.getChargeName())){
            boolQuery.filter(QueryBuilders.termQuery("charge", orderSearchDto.getChargeName()));
        }

        // 1.3.设置订单收费方式精准查询
        if (!StringUtils.isEmpty(orderSearchDto.getPriceMax()) && !StringUtils.isEmpty(orderSearchDto.getPriceMin())){
            boolQuery.filter(QueryBuilders.rangeQuery("price").lte(orderSearchDto.getPriceMax()).gte(orderSearchDto.getPriceMin()));
        }

        // 2.创建条件对象
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder().withQuery(boolQuery);

        // 3.设置高亮条件
        nativeSearchQueryBuilder.withHighlightBuilder(new HighlightBuilder().field("name").preTags("<span style='color:red'>").postTags("</span>"));

        // 设置分组聚合条件
        TermsAggregationBuilder gradeName = AggregationBuilders.terms("grades").field("gradeName");
        nativeSearchQueryBuilder.addAggregation(gradeName);
        TermsAggregationBuilder charge = AggregationBuilders.terms("charges").field("charge");
        nativeSearchQueryBuilder.addAggregation(charge);

        NativeSearchQuery build = nativeSearchQueryBuilder.build();

        // 2.1.设置分页条件
        build.setPageable(PageRequest.of(orderSearchDto.getPage() - 1, orderSearchDto.getRows()));

        // 2.2.设置排序
        if (!StringUtils.isEmpty(orderSearchDto.getSortType()) && !StringUtils.isEmpty(orderSearchDto.getSortField())){
            build.addSort(Sort.by("asc".equals(orderSearchDto.getSortType())?Sort.Direction.ASC:Sort.Direction.DESC, orderSearchDto.getSortField()));
        }


        // 4.把条件对象交给es，进行条件查询
        // 4.1.这种查询是不要高亮和聚合的查询
        // Page<OrderDoc> page = courseRepository.search(build);
        AggregatedPage<OrderDoc> page = elasticsearchRestTemplate.queryForPage(build, OrderDoc.class, new HighlightResultMapper());

        Map<String, List<AggsResult>> map = new HashMap<>();
        // 5.得到聚合结果
        Aggregations aggregations = page.getAggregations();
        aggregations.asMap().entrySet().forEach(e->{
            List<AggsResult> list = new ArrayList<>();
            ((ParsedStringTerms) e.getValue()).getBuckets().forEach(m ->{
                AggsResult aggsResult = new AggsResult();
                aggsResult.setKey(m.getKey().toString());
                aggsResult.setDocCount(m.getDocCount());
                list.add(aggsResult);
            });
            map.put(e.getKey(), list);
        });

        // 得到分页查询返回值
        List<OrderDoc> content = page.getContent();
        long total = page.getTotalElements();
        //return new PageList<>(total, content);
        return new AggsPageList(total, content, map);
    }

}
